---
title: Image
description: A cross-platform and performant React component that loads and renders images.
sourceCodeUrl: 'https://github.com/expo/expo/tree/sdk-52/packages/expo-image'
packageName: 'expo-image'
iconUrl: '/static/images/packages/expo-image.png'
platforms: ['android', 'ios', 'tvos', 'web']
---

import APISection from '~/components/plugins/APISection';
import { APIInstallSection } from '~/components/plugins/InstallSection';
import { YesIcon, NoIcon } from '~/ui/components/DocIcons';
import { Terminal } from '~/ui/components/Snippet';

`expo-image` is a cross-platform React component that loads and renders images.

**Main features:**

- Designed for speed
- Support for many image formats (including animated ones)
- Disk and memory caching
- Supports [BlurHash](https://blurha.sh) and [ThumbHash](https://evanw.github.io/thumbhash/) - compact representations of a placeholder for an image
- Transitioning between images when the source changes (no more flickering!)
- Implements the CSS [`object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) and [`object-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) properties (see [`contentFit`](#contentfit) and [`contentPosition`](#contentposition) props)
- Uses performant [`SDWebImage`](https://github.com/SDWebImage/SDWebImage) and [`Glide`](https://github.com/bumptech/glide) under the hood

#### Supported image formats

|   Format   |   Android   |     iOS     |                          Web                           |
| :--------: | :---------: | :---------: | :----------------------------------------------------: |
|    WebP    | <YesIcon /> | <YesIcon /> |                      <YesIcon />                       |
| PNG / APNG | <YesIcon /> | <YesIcon /> |                      <YesIcon />                       |
|    AVIF    | <YesIcon /> | <YesIcon /> |                      <YesIcon />                       |
|    HEIC    | <YesIcon /> | <YesIcon /> | <NoIcon /> [not adopted yet](https://caniuse.com/heif) |
|    JPEG    | <YesIcon /> | <YesIcon /> |                      <YesIcon />                       |
|    GIF     | <YesIcon /> | <YesIcon /> |                      <YesIcon />                       |
|    SVG     | <YesIcon /> | <YesIcon /> |                      <YesIcon />                       |
|    ICO     | <YesIcon /> | <YesIcon /> |                      <YesIcon />                       |
|    ICNS    | <NoIcon />  | <YesIcon /> |                       <NoIcon />                       |

## Installation

<APIInstallSection />

## Usage

```jsx
import { Image } from 'expo-image';
import { StyleSheet, View } from 'react-native';

const blurhash =
  '|rF?hV%2WCj[ayj[a|j[az_NaeWBj@ayfRayfQfQM{M|azj[azf6fQfQfQIpWXofj[ayj[j[fQayWCoeoeaya}j[ayfQa{oLj?j[WVj[ayayj[fQoff7azayj[ayj[j[ayofayayayj[fQj[ayayj[ayfjj[j[ayjuayj[';

export default function App() {
  return (
    <View style={styles.container}>
      <Image
        style={styles.image}
        source="https://picsum.photos/seed/696/3000/2000"
        placeholder={{ blurhash }}
        contentFit="cover"
        transition={1000}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  image: {
    flex: 1,
    width: '100%',
    backgroundColor: '#0553',
  },
});
```

## API

```js
import { Image } from 'expo-image';
```

<APISection packageName="expo-image" apiName="Image" />

## Generating a blurhash on a server

Images can significantly improve the visual experience, however, they can also slow down app/page loading times due to their large file sizes. To overcome this, you can create placeholder images using blurhash algorithm that provides an immersive experience while deferring the loading of the actual picture until later.

This guide demonstrates how to create a blurhash of an uploaded image on the backend using JavaScript and Express.js. The same techniques and principles apply to other languages and server technologies.

Start by installing a few dependencies: [`multer`](https://github.com/expressjs/multer) for handling multipart requests, [`sharp`](https://github.com/lovell/sharp) for converting files to a data buffer, and the official [`blurhash` JavaScript package](https://github.com/woltapp/blurhash/tree/master/TypeScript).

<Terminal cmd={['$ npm install multer sharp blurhash']} />

Next, import all required functions from installed packages and initialize `multer`:

```js
// Multer is a middleware for handling `multipart/form-data`.
const multer = require('multer');
// Sharp allows you to receive a data buffer from the uploaded image.
const sharp = require('sharp');
// Import the encode function from the blurhash package.
const { encode } = require('blurhash');

// Initialize `multer`.
const upload = multer();
```

Assuming the `app` is a variable that holds a reference to the Express server, an endpoint can be created that accepts an image and returns a JSON response containing the generated blurhash.

```js
app.post('/blurhash', upload.single('image'), async (req, res) => {
  const { file } = req;
  // If the file is not available we're returning with error.
  if (file === null) {
    res.status(400).json({ message: 'Image is missing' });
    return;
  }

  // Users can specify number of components in each axes.
  const componentX = req.body.componentX ?? 4;
  const componentY = req.body.componentY ?? 3;

  // We're converting provided image to a byte buffer.
  // Sharp currently supports multiple common formats like JPEG, PNG, WebP, GIF, and AVIF.
  const { data, info } = await sharp(file.buffer).ensureAlpha().raw().toBuffer({
    resolveWithObject: true,
  });

  const blurhash = encode(
    new Uint8ClampedArray(data),
    info.width,
    info.height,
    componentX,
    componentY
  );
  res.json({ blurhash });
});
```

Additionally, the request can include two parameters: `componentX` and `componentY`, are passed through the algorithm. These values can be calculated or hard-coded on the server or specified by the user. However, they must be within the range of 1 to 9 and have an aspect ratio similar to the uploaded image. A value of 9 will give the best results but may take longer to generate the hash.

The process of generating a blurhash can be accomplished in various languages and server technologies, similar to the one using JavaScript. The key step is to locate an encoder for your chosen language, which can often be found in the [`woltapp/blurhash`](https://github.com/woltapp/blurhash#implementations) repository. Once you have the encoder, you will need to obtain a representation of the image. Some libraries use a default image class (for example, the Swift implementation uses `UIImage`). In other cases, you will have to provide raw byte data. Make sure to check the encoder's documentation to confirm the expected data format.

> When working with raw byte data, ensure that the alpha layer is present (each pixel is represented by red, green, blue, and alpha values). Failing to do so will lead to errors such as "width and height must match the pixels array".
